package com.nagarro.dashboard;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Scanner;
import java.util.StringTokenizer;

import com.nagarro.factory.ItemFactory;
import com.nagarro.inventory.Item;
import com.nagarro.util.Constants;
import com.nagarro.util.Validator;

public class DashBoard {

	ArrayList<Item> items = new ArrayList<Item>();
	Scanner in = new Scanner(System.in);
	Map<Item, Integer> itemList = new HashMap<Item, Integer>();

	ItemFactory itemFactory = new ItemFactory();

	public static void main(String[] args) {
		DashBoard db = new DashBoard();
		db.getInput();
		db.display();
	}

	/**
	 * Take input from the user in the specified format
	 * and continue to do so until the user asks to stop
	 */
	private void getInput() {
		String answer = "";
		String input;
		System.out.println(Constants.INPUT_FORMAT);
		System.out.println(Constants.INPUT_FORMAT_NOTE);
		do {
			System.out.println(Constants.ASK_USER_INPUT);
			input = in.nextLine();
			try {
				addItemObject(input);
				System.out.println(Constants.CONTINUE_OR_NOT);
				answer = in.nextLine();
			} catch (NoSuchElementException e) {
				System.err.println(Constants.ERROR_FIELD_MISSING);
				answer = "y";		// take user input again
				continue;
			} catch (IllegalArgumentException e) {
				answer = "y";		// take user input again
				continue;
			}
		} while (answer.equalsIgnoreCase("y"));
	}

	/**
	 * adds an object of type item to the arraylist after checking for its validity
	 * @param input string input from the user
	 * @return	true if item added successfully, false otherwise
	 * @throws IllegalArgumentException user input not in the correct format
	 * @throws NoSuchElementException All fields not specified by the user
	 */
	private boolean addItemObject(final String input) throws IllegalArgumentException, NoSuchElementException {
		Item item = null;
		String name = "";
		String priceString = "";
		String quantityString = "";
		String type = "";
		StringTokenizer tokenizer = new StringTokenizer(input);
		int numberOfTokens = tokenizer.countTokens();
		
		/* calculate the number of words in name field */
		int wordsInName = numberOfTokens - Constants.NUM_OF_TOKENS_WITHOUT_NAME;
		
		/* Counter to keep a check on if all the 4 fields are provided by the user */
		int counter = 0;
		
		String next;
		while (tokenizer.hasMoreElements()) {
			next= (String) tokenizer.nextElement();
			
			//counter == 0 to ensure name is first element
			if (Constants.ITEM_NAME.equalsIgnoreCase(next)) {
				if(counter == 0){
					while(wordsInName > 0){
						name = name + " " +(String) tokenizer.nextElement();
						wordsInName--;
					}
				counter++;
				} else {
					System.err.println(Constants.ERROR_FIELD_MISSING);
					throw new IllegalArgumentException();
				}
			} else if (Constants.ITEM_PRICE.equalsIgnoreCase(next)) {
				priceString = (String) tokenizer.nextElement();
				counter++;
			} else if (Constants.ITEM_QUANITTY.equalsIgnoreCase(next)) {
				quantityString = (String) tokenizer.nextElement();
				counter++;
			} else if (Constants.ITEM_TYPE.equalsIgnoreCase(next)) {
				type = (String) tokenizer.nextElement();
				type = type.toUpperCase();
				counter++;
			}
		}
		if (counter != 4) {
			System.err.println(Constants.ERROR_FIELD_MISSING);
			throw new IllegalArgumentException();
		} else {
			item = itemFactory.getItem(type);
			
			// Check if item is null
			if (!Validator.isNotNull(item,Constants.ERROR_NULL_VALUE)) {
				throw new IllegalArgumentException();
			}
			item.setName(name);
			
			// Check if priceString is a valid positive double
			if (Validator.isPositiveDouble(priceString,Constants.ERROR_INVALID_PRICE)) {
				item.setPrice(Double.parseDouble(priceString));
			} else {
				throw new IllegalArgumentException();
			}
			
			// Check if priceInt is a valid positive integer
			if (Validator.isPositiveInt(quantityString,Constants.ERROR_INVALID_QUANTITY)) {
				itemList.put(item, Integer.parseInt(quantityString));
				return true;
			} else {
				return false;
			}
		}
	}

	/**
	 * Function to display the final bill for the purchased items
	 */
	private void display() {
		double sum = 0;
		System.out.println("-----------------------------------------------------------------------------------------------");
		System.out.println("                                 Welcome to Naggaro Market                          ");
		System.out.println("-----------------------------------------------------------------------------------------------");
		System.out.println("Item Name                     Price                Quantity               Tax             Total");
		for (Item i : itemList.keySet()) {
			sum += i.getTotal(itemList.get(i));
			System.out.printf("%-20s%15f%20d%25f%20f\n", i.getName(), i.getPrice(), itemList.get(i), i.getTax(), i.getTotal(itemList.get(i)));
		}
		System.out.println("-----------------------------------------------------------------------------------------------");
		System.out.println("                                                   Total Cost                    " + sum);
		System.out.println("-----------------------------------------------------------------------------------------------");

	}
}
